package com.merry.postProcessor.bean;

import org.springframework.beans.BeansException;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.beans.factory.config.ConfigurableBeanFactory;
import org.springframework.beans.factory.config.ConfigurableListableBeanFactory;
import org.springframework.core.Ordered;
import org.springframework.core.PriorityOrdered;
import org.springframework.core.annotation.Order;
import org.springframework.lang.Nullable;

/**
 * 一个钩子接口：它允许用户自己修改一个 bean 的实例。比如实现 Aware接口或者 采用代理的方式包装一个对象。
 *
 * 通常，通过标记接口等填充bean的后处理器将实现 {@link #postProcessBeforeInitialization} ，
 * 而用代理包装bean的后处理程序通常会实现 {@link #postProcessAfterInitialization} 。
 *
 * <h3>注册 BeanPostProcessor</h3>
 * <p>一个 {@code ApplicationContext} 容器会自动检测 {@code BeanPostProcessor} 的实现类（当然需要将它注入进容器）。
 * BeanPostProcessor 会对所有的 bean进行修改。
 * Spring 也支持方法的形式注册一个 BeanPostProcessor 类。比如 {@link ConfigurableListableBeanFactory#addBeanPostProcessor};
 *
 * <h3>排序 Order</h3>
 * <p>所有的 {@code BeanPostProcessor} beans 会被自动注册进 一个 {@code ApplicationContext} 容器，这些bean，会根据 序列号排序
 * {@link PriorityOrdered} and {@link Ordered} 。 这需要让 BeanPostProcessor 的实现类实现任意一个排序接口。
 * 也可以通过 注解的方式来排序，比如 {@link Order @Order}，这种形式，仅限于交给 Spring 管理的 bean。
 *
 * BeanPostProcessor 有几个抽象子类：分别控制者，bean的创建逻辑（这时还没有通过反射创建当前对象） {@see InstantiationAwareBeanPostProcessor}、
 *      bean的销毁逻辑（在bean销毁之前会调用） {@see DestructionAwareBeanPostProcessor}、
 *      用户注册post-processor 的另一种方式 {@link ConfigurableBeanFactory#addBeanPostProcessor}
 *
 * 与 BeanPostProcessor 类似的、操作 BeanFactory的接口 {@see BeanFactoryPostProcessor}
 */
public interface BeanPostProcessor {

    /**
     * 在初始化之前调用的方法。这是在 bean 的实例初始化之前。
     * 也就是bean的生命周期的：
     *  1.通过反射创建bean实例。
     *  2.调用 该方法在初始化之前执行 {@link #postProcessBeforeInitialization}。
     *  3.如果这个bean是一个 {@see InitializingBean} bean，则调用初始化方法，初始化一个bean {@link InitializingBean#afterPropertiesSet()}
     *  4.调用 后置处理器方法。 {@link #postProcessAfterInitialization}
     */
    @Nullable
    default Object postProcessBeforeInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

    /**
     * 方法同上，只不过这是一个在初始化方法之后调用的方法。
     * 这两个方法都提供了默认的实现，也就是返回bean对象。
     */
    @Nullable
    default Object postProcessAfterInitialization(Object bean, String beanName) throws BeansException {
        return bean;
    }

}
